package com.hsu.hsurpc.server.tcp;

import com.hsu.hsurpc.protocal.ProtocolConstant;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.parsetools.RecordParser;

/**
 * TCP 缓冲区处理器包装类，用于处理粘包和半包问题
 * @Author Hsu琛君珩
 * @Date 2024-09-23 17:16
 * @Description
 * @Version: v1.0.0
 */
public class TcpBufferHandlerWrapper implements Handler<Buffer> {

    /**
     * 内部使用的 RecordParser 实例，用于解析 TCP 流中的数据包
     */
    private final RecordParser recordParser;

    /**
     * 构造方法，初始化记录解析器（RecordParser），用于处理粘包和半包
     *
     * @param bufferHandler 用于处理解析后的完整数据包的处理器
     */
    public TcpBufferHandlerWrapper(Handler<Buffer> bufferHandler) {
        recordParser = initRecordParser(bufferHandler);
    }

    /**
     * 处理传入的缓冲区数据，调用内部的 RecordParser 进行数据包解析
     *
     * @param buffer 传入的缓冲区数据
     */
    @Override
    public void handle(Buffer buffer) {
        recordParser.handle(buffer); // 将缓冲区数据传递给 RecordParser 处理
    }

    /**
     * 初始化记录解析器，配置解析逻辑以处理粘包和半包问题
     *
     * @param bufferHandler 用于处理完整数据包的处理器
     * @return 初始化后的 RecordParser 实例
     */
    private RecordParser initRecordParser(Handler<Buffer> bufferHandler) {
        // 初始化 RecordParser，初始状态为固定读取消息头长度
        RecordParser parser = RecordParser.newFixed(ProtocolConstant.MESSAGE_HEADER_LENGTH);
        // 设置解析器的输出处理逻辑
        parser.setOutput(new Handler<Buffer>() {
            int size = -1; // 用于记录消息体的大小
            Buffer resultBuffer = Buffer.buffer(); // 用于存储完整的数据包
            @Override
            public void handle(Buffer buffer) {
                if (size == -1) { // 当 size 为 -1 时，表示当前读取的是消息头
                    size = buffer.getInt(13); // 从消息头中读取消息体的长度
                    parser.fixedSizeMode(size); // 设置 RecordParser 以读取接下来的消息体长度
                    resultBuffer.appendBuffer(buffer); // 将消息头添加到结果缓冲区
                } else {
                    resultBuffer.appendBuffer(buffer); // 读取并追加消息体到结果缓冲区
                    bufferHandler.handle(resultBuffer); // 调用处理器处理完整的数据包
                    parser.fixedSizeMode(ProtocolConstant.MESSAGE_HEADER_LENGTH); // 重置解析器为消息头模式
                    size = -1; // 重置 size 以准备处理下一个数据包
                    resultBuffer = Buffer.buffer(); // 重置结果缓冲区
                }
            }
        });
        return parser;
    }
}
